package com.sun.dream.fish.secret.symmetry;

import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.IDEAEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.encoders.Base64;

import java.nio.charset.StandardCharsets;

public class IDEAExample {
    private static final String KEY = "0123456789ABCDEF01234567"; // 24-byte key
    private static final String IV = "01234567"; // 8-byte initialization vector

    public static void main(String[] args) {
        String plainText = "Hello, World!";
        System.out.println("Original Text: " + plainText);

        String encryptedText = encrypt(plainText);
        System.out.println("Encrypted Text: " + encryptedText);

        String decryptedText = decrypt(encryptedText);
        System.out.println("Decrypted Text: " + decryptedText);
    }

    private static String encrypt(String plainText) {
        byte[] key = KEY.getBytes(StandardCharsets.UTF_8);
        byte[] iv = IV.getBytes(StandardCharsets.UTF_8);
        byte[] input = plainText.getBytes(StandardCharsets.UTF_8);

        IDEAEngine ideaEngine = new IDEAEngine();
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(ideaEngine), new PKCS7Padding());
        CipherParameters cipherParameters = new ParametersWithIV(new KeyParameter(key), iv);
        cipher.init(true, cipherParameters);

        byte[] encryptedBytes = new byte[cipher.getOutputSize(input.length)];
        int length = cipher.processBytes(input, 0, input.length, encryptedBytes, 0);
        try {
            length += cipher.doFinal(encryptedBytes, length);
        } catch (DataLengthException | IllegalStateException | InvalidCipherTextException e) {
            e.printStackTrace();
        }

        byte[] encodedBytes = Base64.encode(encryptedBytes, 0, length);
        return new String(encodedBytes, StandardCharsets.UTF_8);
    }

    private static String decrypt(String encryptedText) {
        byte[] key = KEY.getBytes(StandardCharsets.UTF_8);
        byte[] iv = IV.getBytes(StandardCharsets.UTF_8);
        byte[] encryptedBytes = Base64.decode(encryptedText);

        IDEAEngine ideaEngine = new IDEAEngine();
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(ideaEngine), new PKCS7Padding());
        CipherParameters cipherParameters = new ParametersWithIV(new KeyParameter(key), iv);
        cipher.init(false, cipherParameters);

        byte[] decryptedBytes = new byte[cipher.getOutputSize(encryptedBytes.length)];
        int length = cipher.processBytes(encryptedBytes, 0, encryptedBytes.length, decryptedBytes, 0);
        try {
            length += cipher.doFinal(decryptedBytes, length);
        } catch (DataLengthException | IllegalStateException | InvalidCipherTextException e) {
            e.printStackTrace();
        }

        return new String(decryptedBytes, 0, length, StandardCharsets.UTF_8);
    }
}